home *** CD-ROM | disk | FTP | other *** search
- /* findmsgs.c - find keyed error messages in C++ modules */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include "clexer.h"
-
- #ifdef __ZTC__
- #include <dos.h> /* for WILDCARDS */
- WILDCARDS /* link in wildcard expansion (ZTC) */
- #endif /* __ZTC__ */
-
- extern FILE *yyin;
- char *yytext;
-
- #ifdef __STDC__
- int yyrestart(FILE *); /* flex function definitions */
- int yylex(void);
- void parsefile(const char *filename); /* our functions */
- void printstring(const char *filename,int linenum,const char *tok);
- #else
- int yyrestart(),yylex(),parsefile(),printstring();
- #ifndef EXIT_SUCCESS
- #define EXIT_SUCCESS 0
- #endif
- #endif /* __STDC__ */
-
- #ifdef __STDC__
- int main(int argc,char *argv[])
- #else
- int main(argc,argv)
- int argc;
- char *argv[];
- #endif /* __STDC__ */
- {
- /* search for string constants in the input files (default: stdin) */
- /* and write all string constants to stdout. */
-
- FILE *infile;
- int i,firstfile = 1;
-
- if (argc == 1) {
- parsefile(""); /* default: stdin */
- return EXIT_SUCCESS;
- }
- for (i = 1; i < argc; ++i) {
- infile = fopen(argv[i],"r");
- if (infile == 0) {
- fprintf(stderr,"Unable to read file %s\n",argv[i]);
- continue;
- }
-
- /* due to a bug in flex 2.3.6, we can't use yyrestart() the */
- /* first time. thus we just assign to yyin (which was a pointer */
- /* to stdin). */
-
- if (firstfile)
- yyin = infile;
- else
- yyrestart(infile);
- parsefile(argv[i]);
- fclose(infile);
- firstfile = 0;
- } /* end of for(i) */
-
- return EXIT_SUCCESS;
-
- } /* end of main() */
-
- #ifdef __STDC__
- void parsefile(const char *filename)
- #else
- parsefile(filename)
- char *filename;
- #endif /* __STDC__ */
- {
- /* parse the input file, extracting all string constants. */
-
- int val,last_val,last_linenum;
- char buf[MAXSTRINGLEN];
-
- column = 0;
- linenum = 1;
- last_val = ERROR;
- last_linenum = -1;
- buf[0] = '\0';
-
- while ((val = yylex()) != 0) {
-
- /* adjacent string constants catenate, so we must collect them. */
-
- if (val == STRING) {
- if (last_linenum < 0) /* remember where it started */
- last_linenum = linenum;
-
- /* we assume there is room in the buffer. */
-
- strcat(buf,lexstringtok); /* save it */
- last_val = val;
- }
-
- /* there's a hole in the scanner; it returns ERROR tokens */
- /* sometimes. if we get one we ignore it. */
-
- else if (val != ERROR) {
- if (last_val == STRING) {
- printstring(filename,last_linenum,buf);
- buf[0] = '\0'; /* clear buffer */
- } /* end of if(was string) */
- last_linenum = -1;
- last_val = val;
- } /* end of else(not string now) */
- } /* end of while() */
-
- /* watch for a trailing string constant. */
-
- if (last_val == STRING)
- printstring(filename,last_linenum,buf);
-
- } /* end of parsefile() */
-
- #ifdef __STDC__
- char escape_char(char c)
- #else
- char escape_char(c)
- char c;
- #endif /* __STDC__ */
- {
- /* return the ASCII equivalent of a C escape sequence. the '\' has */
- /* been matched already. */
-
- switch(c) {
- #ifdef __STDC__
- case 'a': /* audible alarm */
- return '\a';
- #endif /* __STDC__ */
- case 'f': /* form feed */
- return '\f';
- case 'r': /* carriage return */
- return '\r';
- case 'v': /* vertical tab */
- return '\v';
- case 'b': /* backspace */
- return '\b';
- case 'n': /* newline */
- return '\n';
- case 't': /* tab */
- return '\t';
- default: /* something ordinary quoted */
- return c;
- } /* end of switch() */
-
- /* NOTREACHED */
-
- } /* end of escape_char() */
-
- #ifdef __STDC__
- char octalchar(char c,const char **tok)
- #else
- char octalchar(c,tok)
- char c,**tok;
- #endif /* __STDC__ */
- {
- /* return the character specified by the octal sequence. not too */
- /* bright about 8 and 9 appearing in the string. */
-
- int i,result = c - '0';
-
- for (i = 0; i < 3 && isdigit(**tok); ++i) {
- result = result * 8 + (**tok - '0');
- ++*tok; /* advance character pointer */
- }
- return (char) result;
-
- } /* end of octalchar() */
-
- #ifdef __STDC__
- int hexval(char c)
- #else
- int hexval(c)
- char c;
- #endif /* __STDC__ */
- {
- /* convert a character to its hexadecimal equivalent. assumes */
- /* isxdigit(c) is true. */
-
- if (isdigit(c))
- return c - '0';
- return toupper(c) - 'A' + 10;
-
- } /* end of hexval() */
-
- #ifdef __STDC__
- char hexchar(char c,const char **tok)
- #else
- char hexchar(c,tok)
- char c,**tok;
- #endif /* __STDC__ */
- {
- /* return the character specified by the hex sequence. */
-
- int i,result = hexval(c);
-
- for (i = 0; i < 2 && isxdigit(**tok); ++i) {
- result = result * 16 + hexval(**tok);
- ++*tok; /* advance character pointer */
- }
- return (char) result;
-
- } /* end of hexchar() */
-
- #ifdef __STDC__
- void printstring(const char *filename,int linenum,const char *tok)
- #else
- printstring(filename,linenum,tok)
- char *filename;
- int linenum;
- char *tok;
- #endif /* __STDC__ */
- {
- /* if the string constant looks like an err_mgr message, print */
- /* it along with its location. */
-
- char *buf,*s,c,esc_c;
- #ifdef __STDC__
- const char *t;
- #else
- char *t;
- #endif /* __STDC__ */
-
- if (*tok != '$')
- return;
- ++tok; /* skip '$' - doesn't go in dict */
- while (isspace(*tok)) /* skip leading blanks */
- ++tok;
- t = tok;
- while (isalpha(*t) || isdigit(*t) || *t == '_') /* identifier? */
- ++t;
- while (isspace(*t)) /* skip trailing blanks */
- ++t;
- if (*t != ':') /* if next char not ':', can't */
- return; /* be dictionary message */
-
- /* replace any '\\' sequences with their ASCII equivalents and */
- /* prefix embedded newlines ("\n" or an actual '\n' character) */
- /* with a '\\' so that the dictionary reader will merge the lines */
- /* properly. */
-
- s = buf = malloc(strlen(tok) * 2 + 1); /* may grow a bit in the process */
- while ((c = *tok++) != '\0') {
- if (c == '\n') {
- *s++ = '\\';
- *s++ = c;
- }
- else if (c == '\\') {
- c = *tok++;
- if (c == '\0')
- break;
- if (isdigit(c)) /* octal character specification */
- *s++ = octalchar(c,&tok); /* advance tok too */
- else if (c == 'x') /* hex character specification */
- *s++ = hexchar(c,&tok); /* advance tok too */
- else {
- esc_c = escape_char(c);
- if (esc_c == '\n') /* quote newlines made in C */
- *s++ = '\\'; /* string constants with "\n" */
- *s++ = esc_c;
- }
- } /* end of if('\\') */
- else
- *s++ = c;
- } /* end of while(c) */
-
- /* last but not least don't quote the final newline, if there is one. */
- /* by definition there is a newline at the end of each complaint */
- /* dictionary entry, and we don't want two. */
-
- if (s > (buf + 1) && s[-1] == '\n') {
- --s;
- s[-1] = '\n'; /* overwrite final '\\' */
- }
- *s = '\0'; /* terminate string */
-
- if (*filename)
- printf("# file %s line %d\n%s\n",filename,linenum,buf);
- else /* coming from stdin */
- printf("# line %d\n%s\n",linenum,buf);
- free(buf);
-
- } /* end of printstring() */